home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / moupp310 / mouse.cpp < prev    next >
C/C++ Source or Header  |  1992-06-28  |  11KB  |  484 lines

  1. /* -------------------------------------------------------------------- */
  2. /* Mouse++ Version 3.1            mouse.cpp            Revised 06/28/92 */
  3. /*                                                                      */
  4. /* General mouse class for Turbo C++/Borland C++.                       */
  5. /* Copyright 1991, 1992 by Carl W. Moreland                             */
  6. /* This source code may be freely distributed as long as the copyright  */
  7. /* notice remains intact.                                               */
  8. /* -------------------------------------------------------------------- */
  9.  
  10. #include <dos.h>
  11. #include <mem.h>
  12. #include <stdlib.h>
  13. #include <graphics.h>
  14. #include "mouse.h"
  15.  
  16. Mouse  mouse;
  17.  
  18. unsigned char Mouse::exists  = 0;
  19. unsigned char Mouse::enabled = 0;
  20. unsigned char Mouse::visible = 0;
  21. unsigned char Mouse::buttons = 0;
  22. unsigned char Mouse::button  = 0;
  23. int           Mouse::x       = 0;
  24. int           Mouse::y       = 0;
  25. int           Mouse::xcount  = 0;
  26. int           Mouse::ycount  = 0;
  27. unsigned char Mouse::hotx    = 0;
  28. unsigned char Mouse::hoty    = 0;
  29. int           Mouse::oldeventmask = 0;
  30. int           Mouse::oldeventseg  = 0;
  31. int           Mouse::oldeventoff  = 0;
  32. unsigned      Mouse::clickThreshold = 250;
  33. unsigned char Mouse::handlerInstalled = 0;
  34. unsigned char Mouse::HeadPtr = 0;
  35. unsigned char Mouse::TailPtr = 0;
  36. unsigned char Mouse::event = 0x00;
  37.  
  38. /* -------------------------------------------------------------------- */
  39.  
  40. Mouse::Mouse(void)            // reset mouse - constructor
  41. {
  42.   int found;
  43.  
  44.   _AX = 0x00;
  45.   geninterrupt(0x33);
  46.   found   = _AX;
  47.   buttons = _BX;
  48.   visible = 0;
  49.  
  50.   if(found)
  51.     exists = 1;
  52.   if(!exists) return;
  53.  
  54.   _ES = 0;
  55.   _DX = 0;
  56.   _CX = 0;                // clear the event handler
  57.   _AX = 0x14;
  58.   geninterrupt(0x33);
  59.   oldeventmask = _CX;            // save the old event handler
  60.   oldeventoff  = _DX;
  61.   oldeventseg  = _ES;
  62.  
  63.   _AX = 0x24;                // get the mouse info
  64.   geninterrupt(0x33);
  65.   Info.majorvers = _BH;
  66.   Info.minorvers = _BL;
  67.   Info.type      = _CH;
  68.   Info.irq       = _CL;
  69. }
  70.  
  71. Mouse::~Mouse(void)            // restore mouse - destructor
  72. {
  73.   if(!exists) return;
  74.   _AX = 0x00;                // reset mouse
  75.   geninterrupt(0x33);
  76.  
  77.   if(oldeventmask)            // restore old event handler
  78.   {
  79.     _ES = oldeventseg;
  80.     _DX = oldeventoff;
  81.     _CX = oldeventmask;
  82.     _AX = 0x14;
  83.     geninterrupt(0x33);
  84.   }
  85. }
  86.  
  87. void Mouse::Enable(void)        // enable the mouse
  88. {
  89.   if(!exists || enabled) return;
  90.  
  91.   if(eventMask && !handlerInstalled)    // re-install event handler
  92.   {
  93.     InstallHandler(eventMask, eventHandler);
  94.     handlerInstalled = 1;
  95.   }
  96.   enabled = 1;
  97. }
  98.  
  99. void Mouse::Disable(void)        // disable the mouse
  100. {
  101.   if(!exists || !enabled) return;
  102.  
  103.   if(handlerInstalled)
  104.   {
  105.     ClearHandler();            // disable the event handler
  106.     ClearClick(LEFTBUTTON);
  107.     ClearClick(RIGHTBUTTON);            // clear the multi-click buffers
  108.     ClearClick(CENTERBUTTON);
  109.   }
  110.   Hide();                // turn the cursor off
  111.   enabled = 0;
  112. }
  113.  
  114. void Mouse::Show()                // show mouse cursor
  115. {
  116.   if(!exists || !enabled) return;
  117.  
  118.   _AX = 0x01;
  119.   geninterrupt(0x33);
  120.   if(visible < 1) visible++;            // visible should now be 1
  121. }
  122.  
  123. void Mouse::Hide(void)            // hide mouse cursor
  124. {
  125.   if(!exists || !enabled) return;
  126.   if(visible < 1) return;
  127.  
  128.   _AX = 0x02;
  129.   geninterrupt(0x33);
  130.   visible = 0;
  131. }
  132.  
  133. void Mouse::Move(int x, int y)        // move cursor to col, row
  134. {                    // col & row are pixel coordinates
  135.   Hide();
  136.  
  137.   if(!exists || !enabled) return;
  138.   _DX = y;
  139.   _CX = x;
  140.   _AX = 0x04;
  141.   geninterrupt(0x33);
  142.  
  143.   Show();
  144. }
  145.  
  146. void Mouse::xLimit(int min, int max)    // set min/max column range
  147. {                    // min & max are pixel coordinates
  148.   if(!exists) return;
  149.   _DX = max;
  150.   _CX = min;
  151.   _AX = 0x07;
  152.   geninterrupt(0x33);
  153. }
  154.  
  155. void Mouse::yLimit(int min, int max)    // set min/max row range
  156. {                    // min & max are pixel coordinates
  157.   if(!exists) return;
  158.   _DX = max;
  159.   _CX = min;
  160.   _AX = 0x08;
  161.   geninterrupt(0x33);
  162. }
  163.  
  164. int Mouse::GetVideoPage(void)        // get the cursor's display page
  165. {
  166.   if(!exists) return 0;
  167.   _AX = 0x1E;
  168.   geninterrupt(0x33);
  169.   return _BX;
  170. }
  171.  
  172. void Mouse::SetVideoPage(int page)    // set the cursor's display page
  173. {
  174.   Hide();
  175.  
  176.   if(!exists) return;
  177.   _BX = page;
  178.   _AX = 0x1D;
  179.   geninterrupt(0x33);
  180.  
  181.   Show();
  182. }
  183.  
  184. void Mouse::MickToPix(int horiz, int vert)
  185. {                             // set the mickey to pixel ratio
  186.   if(!exists) return;
  187.   _DX = vert;
  188.   _CX = horiz;
  189.   _AX = 0x0F;
  190.   geninterrupt(0x33);
  191. }
  192.  
  193. void Mouse::SetSpeedThreshold(unsigned speed)
  194. {                    // set speed change threshold
  195.   if(!exists) return;
  196.   _DX = speed;
  197.   _AX = 0x13;
  198.   geninterrupt(0x33);
  199. }
  200.  
  201. void Mouse::SetCursor(TextCursor& cursor)
  202. {                    // change the text cursor
  203.   if(!exists) return;
  204.   _DX = cursor.arg2;
  205.   _CX = cursor.arg1;
  206.   _BX = cursor.type;
  207.   _AX = 0x0A;
  208.   geninterrupt(0x33);
  209.   hotx = 0;
  210.   hoty = 0;
  211. }
  212.  
  213. void Mouse::SetCursor(GraphicsCursor& cursor)
  214. {                    // change the graphics cursor
  215.   if(!exists) return;
  216.   _ES = FP_SEG(cursor.image);
  217.   _DX = FP_OFF(cursor.image);
  218.   _CX = cursor.hoty;
  219.   _BX = cursor.hotx;
  220.   _AX = 0x09;
  221.   geninterrupt(0x33);
  222.   hotx = cursor.hotx;
  223.   hoty = cursor.hoty;
  224. }
  225.  
  226. void Mouse::Position(void)        // update cursor position &
  227. {                    // button status
  228.   if(!exists || !enabled) return;
  229.   _AX = 0x03;
  230.   geninterrupt(0x33);
  231.   button = _BX;
  232.   x = _CX;
  233.   y = _DX;
  234. }
  235.  
  236. int Mouse::Pressed(int mbutton)        // check press status of button
  237. {
  238.   if(!exists || !enabled) return(0);
  239.  
  240.   if(handlerInstalled)
  241.   {
  242.     if(mbutton == LEFTBUTTON)
  243.       return(event & LB_PRESSED);
  244.     else if(mbutton == RIGHTBUTTON)
  245.       return(event & RB_PRESSED);
  246.     else if(mbutton == CENTERBUTTON)
  247.       return(event & CB_PRESSED);
  248.   }
  249.  
  250.   _BX = mbutton;
  251.   _AX = 0x05;
  252.   geninterrupt(0x33);
  253.   button = _AX;
  254.   int BX = _BX;
  255.   if(BX)
  256.   {
  257.     x = _CX;
  258.     y = _DX;
  259.   }
  260.   return(BX);
  261. }
  262.  
  263. int Mouse::Released(int mbutton)    // check release status of button
  264. {
  265.   if(!exists || !enabled) return(0);
  266.  
  267.   if(handlerInstalled)
  268.   {
  269.     if(mbutton == LEFTBUTTON)
  270.       return(event & LB_RELEASED);
  271.     else if(mbutton == RIGHTBUTTON)
  272.       return(event & RB_RELEASED);
  273.     else if(mbutton == CENTERBUTTON)
  274.       return(event & CB_RELEASED);
  275.   }
  276.  
  277.   _AX = 0x06;
  278.   _BX = mbutton;
  279.   geninterrupt(0x33);
  280.   button = _AX;
  281.   int BX = _BX;
  282.   if(BX)
  283.   {
  284.     x = _CX;
  285.     y = _DX;
  286.   }
  287.   return(BX);
  288. }
  289.  
  290. void Mouse::Motion(void)        // get # of mickeys moved
  291. {
  292.   if(!exists || !enabled) return;
  293.   _AX = 0x0B;
  294.   geninterrupt(0x33);
  295.   xcount = _CX;
  296.   ycount = _DX;
  297. }
  298.  
  299. int Mouse::InBox(int left, int top, int right, int bottom)
  300. {                    // see if mouse is in a box
  301.   if(!exists || !enabled) return(0);
  302.  
  303.   if((x>=left) && (y>=top) && (x<=right) && (y<=bottom))
  304.     return(1);
  305.   return(0);
  306. }
  307.  
  308. void Mouse::Exclude(int left, int top, int right, int bottom)
  309. {                    // set up exclusion area
  310.   if(!exists || !enabled) return;
  311.  
  312.   if((x >= (left-15+hotx)) && (y >= (top-15+hoty)) &&
  313.      (x <= (right+hotx)) && (y <= (bottom+hoty)))
  314.     Hide();
  315.   else
  316.     Show();
  317. }
  318.  
  319. void Mouse::SetClickThreshold(unsigned time)
  320. {
  321.   clickThreshold = time;        // time is in milliseconds
  322. }
  323.  
  324. int Mouse::MultiClick(int mbutton)    // check for multiple clicks
  325. {
  326.   if(!exists || !enabled) return(0);
  327.  
  328.   return Click[mbutton].count;
  329. }
  330.  
  331. int Mouse::DoubleClick(int mbutton)     // check for double clicks
  332. {
  333.   if(!exists || !enabled) return(0);
  334.  
  335.   return (Click[mbutton].count == 2);
  336. }
  337.  
  338. void Mouse::ClearClick(int mbutton)    // clear the MultiClick buffer
  339. {
  340.   if(!exists || !enabled) return;
  341.  
  342.   Click[mbutton].count = 0;
  343. }
  344.  
  345. /* ----- Event Driver routines ---------------------------------------- */
  346.  
  347. void Mouse::InstallHandler(unsigned mask, void interrupt (*handler)(void))
  348. {
  349.   if(!exists) return;            // set up an event handler
  350.  
  351.   _ES = FP_SEG(handler);
  352.   _DX = FP_OFF(handler);
  353.   _CX = mask;
  354.   _AX = 0x14;
  355.   geninterrupt(0x33);
  356.  
  357.   handlerInstalled = 1;
  358.   HeadPtr = 0;
  359.   TailPtr = 0;
  360.   eventMask = mask;
  361.   eventHandler = handler;
  362. }
  363.  
  364. void Mouse::ClearHandler(void)        // clear the event handler
  365. {
  366.   if(!exists) return;
  367.  
  368.   _ES = 0;
  369.   _DX = 0;
  370.   _CX = 0;
  371.   _AX = 0x14;
  372.   geninterrupt(0x33);
  373.  
  374.   handlerInstalled = 0;
  375.   HeadPtr = 0;
  376.   TailPtr = 0;
  377. }
  378.  
  379. /* Mouse::Save - stuff the event info in the event buffer */
  380.  
  381. void Mouse::Save(int event, int button, int x, int y, int xcount, int ycount)
  382. {
  383.   static unsigned char keymask;
  384.   static long time;
  385.  
  386.   disable();
  387.  
  388.   if((HeadPtr == TailPtr-1) ||        // see if the buffer is full
  389.      (HeadPtr == MOUSE_BUFFER_SIZE-1 && TailPtr == 0))
  390.     return;
  391.  
  392.   if((event & LB_PRESSED) || (event & RB_PRESSED) || (event & CB_PRESSED))
  393.   {
  394.     time = *(long far *)MK_FP(0x0040, 0x006C)*55;
  395.     keymask = *(char far *)MK_FP(0x0040, 0x0017);
  396.  
  397.     button += (keymask << 4);        // add it to the button mask
  398.     if(keymask & 0x03)
  399.       button += 0x08;
  400.   }
  401.   else
  402.     time = 0;                // no button press so time not needed
  403.  
  404.   Buffer[HeadPtr].event  = event;    // store the info in the event buffer
  405.   Buffer[HeadPtr].button = button;
  406.   Buffer[HeadPtr].x      = x;
  407.   Buffer[HeadPtr].y      = y;
  408.   Buffer[HeadPtr].xcount = xcount;
  409.   Buffer[HeadPtr].ycount = ycount;
  410.   Buffer[HeadPtr].time   = time;
  411.  
  412.   if(++HeadPtr >= MOUSE_BUFFER_SIZE)    // increment the head ptr
  413.     HeadPtr = 0;
  414.  
  415.   enable();
  416. }
  417.  
  418. void interrupt MouseHandler(void)    // default event handler
  419. {
  420.   mouse.Save(_AX,_BX,_CX,_DX,_DI,_SI);  // save the normal stuff
  421.   EventExit();                              // required for interrupt function
  422. }
  423.  
  424. /* Mouse::GetEvent - read the event buffer and put info into the class */
  425.  
  426. void Mouse::GetEvent(void)
  427. {
  428.   if(!exists || !enabled) return;
  429.  
  430.   int mbutton;
  431.  
  432.   if(HeadPtr != TailPtr)
  433.   {
  434.     event  = Buffer[TailPtr].event;
  435.     button = Buffer[TailPtr].button;
  436.     x      = Buffer[TailPtr].x;
  437.     y      = Buffer[TailPtr].y;
  438.     xcount = Buffer[TailPtr].xcount;
  439.     ycount = Buffer[TailPtr].ycount;
  440.  
  441.     if(Buffer[TailPtr].time)            // store info for MultiClick()
  442.     {
  443.       if(event & LB_PRESSED)
  444.         mbutton = LEFTBUTTON;
  445.       else if(event & RB_PRESSED)
  446.         mbutton = RIGHTBUTTON;
  447.       else if(event & CB_PRESSED)
  448.         mbutton = CENTERBUTTON;
  449.  
  450.       if((Buffer[TailPtr].time - Click[mbutton].time) < clickThreshold)
  451.         Click[mbutton].count++;
  452.       else
  453.         Click[mbutton].count = 1;
  454.  
  455.       Click[mbutton].time = Buffer[TailPtr].time;
  456.     }
  457.  
  458.     if(++TailPtr >= MOUSE_BUFFER_SIZE)
  459.       TailPtr = 0;
  460.   }
  461.   else
  462.   {
  463.     event  = 0;
  464.     xcount = 0;
  465.     ycount = 0;
  466.   }
  467. }
  468.  
  469. void Mouse::ClearEvent(void)        // clear the current event
  470. {
  471.   event  = 0;
  472.   button = 0;
  473.   x      = 0;
  474.   y      = 0;
  475.   xcount = 0;
  476.   ycount = 0;
  477. }
  478.  
  479. void Mouse::ClearBuffer(void)        // clear the event buffer
  480. {
  481.   HeadPtr = 0;
  482.   TailPtr = 0;
  483. }
  484.